package com.test.uilt;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.test.manage.building.bean.BuildingConstants;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class PhotoUtils {

    /**
     * 用于启用多线程时 控制台输出记录图片总数量
     */
    public static int photoSize = 0;

    /**
     * 用于启用多线程时 控制台输出已完成的数量
     */
    public static int photoCount = 0;


    /**
     * 获取所有文件
     * @param photoPath 读取文件路径下所有文件
     * @return
     */
    public static File[] getPhotoAll(String photoPath) {
        return getPhotoAll(photoPath, "", 0, 0, BuildingConstants.PHOTO_QUALITY_EXCELLENT);
    }

    /**
     * 获取指定文件类型的文件
     * @param photoPath 读取文件路径下所有文件
     * @param photoType 指定类型 传空则获取全部文件
     * @return
     */
    public static File[] getPhotoAll(String photoPath,String photoType) {
        return getPhotoAll(photoPath, photoType, 0, 0, BuildingConstants.PHOTO_QUALITY_EXCELLENT);
    }

    /**
     * 获取所有文件类型的文件  设定尺寸
     * @param photoPath 读取文件路径下文件
     * @return
     */
    public static File[] getPhotoAll(String photoPath,int width, int height) {
        return getPhotoAll(photoPath,"" , width, height, BuildingConstants.PHOTO_QUALITY_EXCELLENT);
    }

    /**
     * 获取指定文件类型的文件  设定尺寸
     * @param photoPath 读取文件路径下所有文件
     * @param photoType 指定类型 传""则获取全部文件
     * @param width 图片宽
     * @param height 图片宽
     * @param quality 图片质量
     * @return
     */
    public static File[] getPhotoAll(String photoPath,String photoType, int width, int height, float quality) {
        /*获取文件目录*/
        File dir = new File(photoPath);

        if (!(dir.exists() && dir.isDirectory())) {
            try {
                throw new Exception(" [ " + dir.getAbsolutePath() + " ] 目录不存在，请检查目录是否填写正确或根据提示手动创建目录并复制图片到此文件夹下。");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /*列出该目录下所有的.jpg*/
        File[] files = dir.listFiles(new FilenameFilter() {
            //获取.jpg图片，创建一个过滤文件名的Filter
            @Override
            public boolean accept(File dir, String name) {
                /*如果不指定类型 排除文件夹*/
                if (name != null && "".equals("") && name.split("\\.").length > 1) {
                    //检测文件名是否是以.jpg结尾，是返回true，否则继续检测下一个文件
                    if (name.toLowerCase().endsWith(photoType)) {
                        return true;
                    }
                }
                return false;
            }
        });

        if (files == null || files.length == 0) {
            try {
                throw new Exception("目录[ " + photoPath + " ]下为空, 请检查是否复制图片到此文件夹。");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //如果传压缩的尺寸
        if (width >0 && height > 0) {
            String destPath = resizeImage(files, photoPath, width, height, quality);
            return new File(destPath).listFiles();
        }
        return files;
    }

    /**
     * 图片转换像素
     * 暂不使用测试图片转换比较模糊
     * @param files 原图片路径下所有图片
     * @param destPath  转换大小后图片路径
     * @param width   转换后图片宽度
     * @param height  转换后图片高度
     */
    public static String resizeImage(File[] files, String destPath, int width, int height, float quality) {
        photoSize = files.length;
        //将其保存在原图同级resizeImage下
        destPath = (destPath + "/resizeImage/" + DateUtil.getLongTime() + "/").replace("//", "/");

        //将其保存在/resizeImage下
        File destFile = new File(destPath);
        if(!destFile.exists()) {
            destFile.mkdirs();
        }
        //开启过多的线程容易宕机
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        List<Future<Integer>> futureList = new ArrayList<Future<Integer>>(files.length);
        for(File file : files){
            //也可以使用实现Runnable的方法
            String finalDestPath = destPath;
            Callable<Integer> runnale = new Callable<Integer>() {
                @Override
                public  Integer call() {
                    //处理业务
                    try {
                        imageResize(file,finalDestPath + file.getName(),width, height,quality);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return 0;//无用返回
                }
            };
            Future<Integer> future = executorService.submit(runnale);
            futureList.add(future);
        }
        //主线程阻塞，等待子线程执行完毕并返回结果
        //否则新生成的图片还没放到指定位置，主线程就会去读取这个文件夹，此时文件夹内还是空的
        syncFuture(futureList);
        //关闭线程池
        executorService.shutdown();
        System.out.print("图片存放地址 [ " + destPath + " ] 下");
        return destPath;
    }

    /**
     * 缩放图片(压缩图片质量，改变图片尺寸)
     * 若原图宽度小于新宽度，则宽度不变！
     * @param originalFile
     * @param resizedPath
     * @param maxWidth
     * @param maxHeight
     * @param quality 图片质量参数 0.7f 相当于70%质量
     * @throws IOException
     */
    public static void imageResize(File originalFile, String resizedPath,
                                   int maxWidth,int maxHeight, float quality) throws IOException {

        if (quality > 1) {
            throw new IllegalArgumentException(
                    "图片质量需设置在0.1-1范围");
        }
        if (StringUtils.isBlank(resizedPath)) {
            throw new IllegalArgumentException(
                    "下载位置为空，请设置下载位置");
        }

        File resizedFile = new File(resizedPath);

        ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());
        Image i = ii.getImage();
        Image resizedImage = null;

        int iWidth = i.getWidth(null);
        int iHeight = i.getHeight(null);

        int newWidth = maxWidth;
        if(iWidth < maxWidth){
            newWidth = iWidth;
        }


        if (iWidth >= iHeight) {
            resizedImage = i.getScaledInstance(newWidth, (newWidth * iHeight)
                    / iWidth, Image.SCALE_SMOOTH);
        }



        int newHeight = maxHeight;
        if(iHeight < maxHeight){
            newHeight = iHeight;
        }

        if(resizedImage==null && iHeight >= iWidth){
            resizedImage = i.getScaledInstance((newHeight * iWidth) / iHeight,
                    newHeight, Image.SCALE_SMOOTH);
        }

        // This code ensures that all the pixels in the image are loaded.
        Image temp = new ImageIcon(resizedImage).getImage();

        // Create the buffered image.
        BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null),
                temp.getHeight(null), BufferedImage.TYPE_INT_RGB);

        // Copy image to buffered image.
        Graphics g = bufferedImage.createGraphics();

        // Clear background and paint the image.
        g.setColor(Color.white);
        g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
        g.drawImage(temp, 0, 0, null);
        g.dispose();

        // Soften.
        float softenFactor = 0.05f;
        float[] softenArray = { 0, softenFactor, 0, softenFactor,
                1 - (softenFactor * 4), softenFactor, 0, softenFactor, 0 };
        Kernel kernel = new Kernel(3, 3, softenArray);
        ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
        bufferedImage = cOp.filter(bufferedImage, null);

        // Write the jpeg to a file.
        FileOutputStream out = new FileOutputStream(resizedFile);

        // Encodes image as a JPEG data stream
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);

        JPEGEncodeParam param = encoder
                .getDefaultJPEGEncodeParam(bufferedImage);

        param.setQuality(quality, true);

        encoder.setJPEGEncodeParam(param);
        encoder.encode(bufferedImage);

        System.out.println("共" + photoSize + "张图片，已复制" + photoCount++ + "张，已完成 [ " + Arith.round(Double.valueOf(photoCount)/Double.valueOf(photoSize) *100, 0) + "% ]");

        // Create the buffered image.
        try {
            out.close();
        }  catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    } // Example usage
    /**
     * 随机取一张图片
     * @param files
     * @return
     * @throws Exception
     */
    public static File getRandomSelection(File[] files){
        //随机取图片
        int fileLength = files.length;
        int number = new Random().nextInt(fileLength);
        return files[number];
    }

    /**
     * 拷贝图片并设置名称
     * @param file
     * @param dowloadedPath
     * @param photoName
     */
    public static void copyPhotoToDest(File file, String dowloadedPath, String photoName) {
        /*获取目标文件夹，如果不存在就建立该文件夹*/
        File destDir = new File(dowloadedPath);
        if(!destDir.exists()) {
            destDir.mkdirs();
        }
        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream(file);
            fos = new FileOutputStream(new File(destDir, photoName));
            /*将文件重新写入目标文件夹*/
            copy(fis, fos);
        } catch (Exception e) {
            e.getMessage();
        }finally {
            try {
                if (null != fis) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (null != fos) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }


    /**
     * 给时间添加秒
     * @param dateTmie
     * @return
     */
    public static String getBuildingPhotoDATE_TIME(String dateTmie) {
        dateTmie = dateTmie.replace("\"", "");
        dateTmie = dateTmie.replace(",", "");
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = df.parse(dateTmie);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //加一秒
        date.setTime(date.getTime() + 1000);

        //改为插入语句格式
        return "\"" + df.format(date) + "\",";
    }

    /**
     * 判断磁盘路径 不存在创建
     * @param dowLoadPath
     */
    public static void isChartPathExist(String dowLoadPath) {
        File file = new File(dowLoadPath);
        if(!file.exists()){
            //先得到文件的上级目录，并创建上级目录，在创建文件
            file.getParentFile().mkdir();
            try {
                //创建文件
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 拷贝方法 根据机器性能增大缓存
     * @param in
     * @param out
     */
    public static void copy(InputStream in, OutputStream out){
        byte[] buf = new byte[4096];
        int len = 0;
        /*读取文件内容并写入文件字节流中*/
        try {
            while((len = in.read(buf))!=-1) {
                out.write(buf, 0, len);
            }
        } catch (Exception e) {
            e.getMessage();
        }finally {
            try {
                if (null != out) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void syncFuture(List<Future<Integer>> futureList){
        //主线程阻塞，等待子线程执行完毕并返回结果
        for(Future<Integer> future : futureList) {
            try {
                future.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}
